<?php
/*
 * description：
 * author：wh
 * email：
 * createTime：{2024/6/28} {14:36} 
 */

namespace wanghua\general_utility_tools_php\alibaba;

use wanghua\general_utility_tools_php\http\Curl;
use wanghua\general_utility_tools_php\tool\Tools;

/**
 * 授权
 *
 * 注意：
 * 分销自研自用版不需要授权，直接使用永久accessToken
 * 请把当前账号添加为应用的日常测试账号
 *
 * Class Auth
 * @package app\index\logic\alibaba
 */
class AlibabaAuth
{
    public $base_url = '';//不同业务线，授权地址不一样
    public $config = [];
    public $request_body = [];
    public function __construct($config)
    {
        $this->config = $config;
    }

    function trusteeshipAuth(){
        //待开发
    }

    /**
     * desc：授权分为托管式授权和WEB端授权，这里是WEB端授权（后去code临时凭证）
     *
     * author：wh
     * @param string $appKey app注册时，分配给app的唯一标识
     * @param string $redirect_uri app的入口地址，授权临时令牌会以queryString的形式跟在该url后返回。注意参数中回调地址的域名必须与app注册时填写的回调地址的域名匹配。
     * @param string $site site参数标识当前授权的站点，直接填写1688
     * @param string $state 可选，app自定义参数，回跳到redirect_uri时，会原样返回
     * return 用户输入用户名密码，并确认授权，返回临时授权码code给app，具体返回方式，参照redirect_uri说明
     */
    function webAppAuth($redirect_uri,$site='1688',$state=''){
        $appKey = $this->config['appkey'];

        $url = "https://auth.1688.com/oauth/authorize?client_id={$appKey}&site={$site}&redirect_uri={$redirect_uri}&state={$state}";


        //$res = Curl::curl_post($url,[]);
        return "<script>location.href='{$url}'</script>";
    }

    /**
     * desc：使用code获取令牌【code有效期（2分钟）】
     *
     * 注：此接口必须使用POST方法提交；必须使用https
    getToken接口参数说明：
    a) grant_type为授权类型，使用authorization_code即可
    b) need_refresh_token为是否需要返回refresh_token，如果返回了refresh_token，原来获取的refresh_token也不会失效，除非超过半年有效期
    c) client_id为app唯一标识，即appKey
    d) client_secret为app密钥
    e) redirect_uri为app入口地址
    f) code为授权完成后返回的一次性令牌
    g) 调用getToken接口不需要签名
    注：如果超过code有效期（2分钟）或者已经使用code获取了一次令牌，code都将失效，需要返回第二步重新获取code
     * author：wh
     */
    function getTokenByCode($code,$redirect_uri){
        $appkey = $this->config['appkey'];
        $secret = $this->config['appsecret'];
        $url = "https://gw.open.1688.com/openapi/";
        $urlPath = "http/1/system.oauth2/getToken/".$appkey;
        $paramstr = "?grant_type=authorization_code&need_refresh_token=true&client_id={$appkey}&client_secret={$secret}&redirect_uri={$redirect_uri}&code={$code}";

        $url = $url.$urlPath.$paramstr;
        return Curl::curl_post($url,[]);
    }

    /**
     * 生成签名
     *
    1、 构造urlPath。urlPath是url 中的一部分，从协议开始截取，到“?”为止，包含了协议、namespace、apiName和apiVersion，如urlPath=http/1/system/currentTime/1688

    2、 拼装参数。首先将所有参数按照key+value拼装得到一个字符串数组（如[b1,a2]），然后对数组进行排序（[a2,b1]），最后将排序后的数组合并为字符串（a2b1）

    3、 合并。把前两步的字符串拼接（http/1/system/currentTime/1688a2b1）

    4、 执行hmac_sha1算法。 Signature=uppercase (hex (hmac_sha1 (concatString, secretKey))，假设secretKey=test123，那么得到的签名为2F1E96587451DE0E171978F4AAE1A90FF9B2F94B

    a) concatString为合并后的字符串

    b) secretKey为签名密钥，与urlPath中的appKey（1000000）对应

    c) hmac_sha1为通用的hmac_sha1算法，各编程语言一般都对应类库

    d) hex为转为十六进制

    e) uppercase为转为大写字符
     * author：wh
     * @param string $urlPath eg: param2/1/com.alibaba.trade/alibaba.trade.fastCreateOrder/7571561
     * @param array $params 请求参数
     * @return string
     */
    public function signature($urlPath,$params)
    {
        $accessToken = $this->config['accessToken'];
        $params['access_token'] = $accessToken;
        //$url = 'http://gw.open.1688.com/openapi';//1688开放平台使用gw.open.1688.com域名
        //$appKey = $this->config['appkey'];
        $appSecret = $this->config['appsecret'];

        //dump('$urlPath: '.$urlPath);
        //$apiInfo = 'param2/1/system/currentTime/' . $appKey;//此处请用具体api进行替换
        //$urlPath = $urlPath . $appKey;//此处请用具体api进行替换

        //配置参数，请用apiInfo对应的api参数进行替换
        $aliParams = array();
        foreach ($params as $key => $val) {
            $aliParams[] = $key . $val;
        }
        sort($aliParams);
        $sign_str = join('', $aliParams);
        $sign_str = $urlPath . $sign_str;
        $code_sign = strtoupper(bin2hex(hash_hmac("sha1", $sign_str, $appSecret, true)));

        return $code_sign;
    }

    /**
     * desc：发起请求，自动完成签名并返回结果
     * author：wh
     * @param string $urlPath eg: param2/1/com.alibaba.trade/alibaba.trade.fastCreateOrder/23222222
     * @param array $request_data 接口请求数据
     */
    function request($urlPath, $request_data){
        set_time_limit(0);
        $request_params_str = '';
        foreach ($request_data as $k=>$v){
            if($request_params_str == ''){
                $request_params_str .= $k.'='.$v;
            }else{
                $request_params_str .= '&'.$k.'='.$v;
            }
        }
        $accessToken = $this->config['accessToken'];
        //dump($request_params_str);
        $_aop_signature = $this->signature($urlPath,$request_data);
        //dump($_aop_signature);
        //$request_data['_aop_signature'] = $_aop_signature;

        $url = $this->base_url.$urlPath.'?'.$request_params_str.'&access_token='.$accessToken.'&_aop_signature='.$_aop_signature;
        //dump($url);
        $this->request_body = $url;
        $res = Curl::curl_post($url,[]);
        return $res;
    }
}